﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Web.Mvc;
using System.Globalization;

namespace TeamCommunitySolution.Extensions
{
    /// <summary>
    /// Theme view engine.
    /// </summary>
    public class ThemeViewEngine : WebFormViewEngine
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ThemeViewEngine"/> class.
        /// </summary>
        public ThemeViewEngine()
        {
            base.ViewLocationFormats = new string[] {
            "~/Views/{1}/{0}.aspx",
            "~/Views/{1}/{0}.ascx",
            "~/Views/Shared/{0}.aspx",
            "~/Views/Shared/{0}.ascx"
        };

            base.MasterLocationFormats = new string[] {
            "~/Content/{2}/Site.master"
        };

            base.PartialViewLocationFormats = new string[] {
            "~/Views/{1}/{0}.aspx",
            "~/Views/{1}/{0}.ascx",
            "~/Views/Shared/{0}.aspx",
            "~/Views/Shared/{0}.ascx"
        };
        }

        /// <summary>
        /// Finds the view.
        /// </summary>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="viewName">Name of the view.</param>
        /// <param name="masterName">Name of the master.</param>
        /// <param name="useCache">if set to <c>true</c> [use cache].</param>
        /// <returns>The page view.</returns>
        public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            if (string.IsNullOrEmpty(viewName))
            {
                throw new ArgumentException("Value is required.", "viewName");
            }

            string themeName = this.GetThemeToUse(controllerContext);

            string[] searchedViewLocations;
            string[] searchedMasterLocations;

            string controllerName =
                controllerContext.RouteData.GetRequiredString("controller");

            string viewPath = this.GetViewPath(this.ViewLocationFormats, viewName,
                              controllerName, out searchedViewLocations);
            string masterPath = this.GetMasterPath(this.MasterLocationFormats, viewName,
                                controllerName, themeName, out searchedMasterLocations);

            if (!(string.IsNullOrEmpty(viewPath)) && (!(masterPath == string.Empty) || string.IsNullOrEmpty(masterName)))
            {
                return new ViewEngineResult((this.CreateView(controllerContext, viewPath, masterPath)), this);
            }
            return new ViewEngineResult(
              searchedViewLocations.Union<string>(searchedMasterLocations));
        }


        /// <summary>
        /// Finds the partial view.
        /// </summary>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="partialViewName">Partial name of the view.</param>
        /// <param name="useCache">if set to <c>true</c> [use cache].</param>
        /// <returns>The partial view.</returns>
        public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            if (string.IsNullOrEmpty(partialViewName))
            {
                throw new ArgumentException("Value is required.", partialViewName);
            }

            string themeName = this.GetThemeToUse(controllerContext);

            string[] searchedLocations;

            string controllerName = controllerContext.RouteData.GetRequiredString("controller");

            string partialPath = this.GetViewPath(this.PartialViewLocationFormats, partialViewName, controllerName, out searchedLocations);

            if (string.IsNullOrEmpty(partialPath))
            {
                return new ViewEngineResult(searchedLocations);
            }
            return new ViewEngineResult(this.CreatePartialView(controllerContext, partialPath), this);
        }

        /// <summary>
        /// Gets the theme to use.
        /// </summary>
        /// <param name="controllerContext">The controller context.</param>
        /// <returns>return the theme to use</returns>
        private string GetThemeToUse(ControllerContext controllerContext)
        {
            if (controllerContext.HttpContext.Request.QueryString.AllKeys.Contains("theme"))
            {
                string themeName = controllerContext.HttpContext.Request.QueryString["theme"];
                controllerContext.HttpContext.Session.Add("Theme", themeName);
            }
            else if (controllerContext.HttpContext.Session["Theme"] == null)
            {
                controllerContext.HttpContext.Session.Add("Theme", ConfigurationManager.AppSettings["Theme"]);
            }

            return controllerContext.HttpContext.Session["Theme"].ToString();
        }

        /// <summary>
        /// Gets the view path.
        /// </summary>
        /// <param name="locations">The locations.</param>
        /// <param name="viewName">Name of the view.</param>
        /// <param name="controllerName">Name of the controller.</param>
        /// <param name="searchedLocations">The searched locations.</param>
        /// <returns>View path.</returns>
        private string GetViewPath(string[] locations, string viewName, string controllerName, out string[] searchedLocations)
        {
            string path = null;

            if (viewName.StartsWith("~/"))
            {
                searchedLocations = new string[0];
                return viewName;
            }

            searchedLocations = new string[locations.Length];

            for (int i = 0; i < locations.Length; i++)
            {
                path = string.Format(CultureInfo.InvariantCulture, locations[i], new object[] { viewName, controllerName });
                if (this.VirtualPathProvider.FileExists(path))
                {
                    searchedLocations = new string[0];
                    return path;
                }

                searchedLocations[i] = path;
            }

            return null;
        }

        /// <summary>
        /// Gets the master path.
        /// </summary>
        /// <param name="locations">The locations.</param>
        /// <param name="viewName">Name of the view.</param>
        /// <param name="controllerName">Name of the controller.</param>
        /// <param name="themeName">Name of the theme.</param>
        /// <param name="searchedLocations">The searched locations.</param>
        /// <returns></returns>
        private string GetMasterPath(string[] locations, string viewName, string controllerName, string themeName, out string[] searchedLocations)
        {
            string path = null;

            searchedLocations = new string[locations.Length];

            for (int i = 0; i < locations.Length; i++)
            {
                path = string.Format(CultureInfo.InvariantCulture, locations[i], new object[] { viewName, controllerName, themeName });
                if (this.VirtualPathProvider.FileExists(path))
                {
                    searchedLocations = new string[0];
                    return path;
                }

                searchedLocations[i] = path;
            }

            return null;
        }


    }
}
